﻿using SCG.General;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SCG.SolarVengeanceEngine.StarShips
{
    public class Carrier : StarShip
    {
        //constructor
        public Carrier(SVGame game, Player owner, int engines, int bays, StarSystem origin)
            : base(game, owner, engines, bays, origin)
        {
        }

        //starship name
        public override string Name
        {
            get
            {
                return "Carrier";
            }
        }

        //ship type
        public override StarShipType ShipType
        {
            get
            {
                return StarShipType.Carrier;
            }
        }

        //description
        public override string Description
        {
            get
            {
                return "Carriers contains a number of Bays, and each Bay can hold one StarShip.  You can load StarShips " +
                    "onto the Carrier and use it to move them all to a different location at once.";
            }
        }

        //is it full?
        public bool IsFull
        {
            get
            {
                return _carried.Count >= Value;
            }
        }

        //show how many are being carried
        public override string PrimarySystemMark
        {
            get
            {
                if (!OwnedByCurrentPlayer)
                    return base.PrimarySystemMark;
                if (_carried.Count == 0)
                    return base.PrimarySystemMark;
                else
                    return base.PrimarySystemMark + " S" + _carried.Count;
            }
        }

        //can it execute a launch?
        public override bool CanExecuteOrder(OrderType ot)
        {
            if (ot == OrderType.Launch)
                return _carried.Count > 0;
            else if (ot == OrderType.BoardCarrier)
                return false;
            else
                return base.CanExecuteOrder(ot);
        }

        //process damage, destroy carried StarShips
        protected internal override void ProcessDamage(int damage, bool canDamageEngines)
        {
            base.ProcessDamage(damage, canDamageEngines);
            while (_carried.Count > Value)
            {
                StarShip ship = _carried.RemoveRandomValue;
                Game.DestroyStarShip(ship);
            }
        }

        //destroy carried StarShips when Carrier destroyed
        protected internal override void ProcessDestruction()
        {
            while (_carried.Count > 0)
            {
                StarShip ship = _carried[0];
                _carried.RemoveAt(0);
                Game.DestroyStarShip(ship);
            }
        }

        //embark a StarShip
        public void Embark(StarShip ship)
        {
            _carried.Add(ship);
            ship.IsEmbarked = true;
            Game.SetObjectAt(ship.X, ship.Y, null);

            //report to host
            if (Game.Host != null)
                Game.Host.StarShipEmbarked(ship, this);

            //state change
            Game.SubmitStateChange(StateChange.EmbarkStarShip, ship, this);
        }

        //launch ships
        public void Launch()
        {
            foreach (StarShip ship in _carried)
            {
                int x = X;
                int y = Y;
                Game.SetToClosestEmpty(ref x, ref y);
                Game.SetObjectAt(x, y, ship);
                ship.X = x;
                ship.Y = y;

                //report to host
                if (Game.Host != null)
                    Game.Host.StarShipLaunched(ship, this);

                ship.IsEmbarked = false;
            }

            _carried.Clear();
            Game.SubmitStateChange(StateChange.LaunchShips, this);
        }

        //persistence
        protected override string SubClassPersist()
        {
            Tokenizer tok = new Tokenizer();
            tok.AppendToken(_carried.Count);
            foreach (StarShip ship in _carried)
                tok.AppendToken(ship.Code);
            return base.SubClassPersist() + tok.Result;
        }
        protected override void SubClassParse(SVTokenizer tok)
        {
            base.SubClassParse(tok);
            int count = tok.TokenInt;
            if (count > 0)
            {
                _codes = new List<string>();
                while (count > 0)
                    _codes.Add(tok.TokenString);
            }
        }
        public override void Relink()
        {
            if (_codes != null && _codes.Count > 0)
                while (_codes.Count > 0)
                {
                    string code = _codes[0];
                    _codes.RemoveAt(0);
                    _carried.Add(Game.FindStarShip(code));
                }
        }

        //private members
        private List<string> _codes;
        private RandomList<StarShip> _carried = new RandomList<StarShip>();
    }
}
